package com.wimcorp.magic.abilities;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Transient;

import com.wimcorp.magic.abilities.trigger.AbilityTrigger;
import com.wimcorp.magic.abilities.trigger.OnAttack;
import com.wimcorp.magic.abilities.trigger.OnEnterBattlefield;
import com.wimcorp.magic.cards.PlayingCard;

@Embeddable
public class AbilityHolder {

	/*
	 * @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	 * 
	 * @JoinTable(name = "abilityholder_ability", joinColumns = @JoinColumn(name
	 * = "playingcard_id", referencedColumnName = "id"), inverseJoinColumns =
	 * @JoinColumn(name = "ability_id", referencedColumnName = "id"))
	 * 
	 * @OrderColumn
	 */
	@OneToMany(cascade = CascadeType.ALL)
	private Map<Long, Ability> abilities = new HashMap<Long, Ability>();

	public AbilityHolder() {
	}

	public void addAbility(Ability ability) {
		if (abilities.get(ability.getIdentifier()) == null) {
			abilities.put(ability.getIdentifier(), ability);
		}else{
			//This is needed for loading the data the first time
			long identifier = ability.getIdentifier();
			ability.setIdentifier(abilities.get(identifier).getIdentifier() +1);
			System.err.print("Ability with identifier " +identifier + " already in abilities... " );
			addAbility(ability);
		}
	}

	public void addAbilities(Set<Ability> abilities) {
		for (Ability ability : abilities) {
			addAbility(ability);
		}

	}

	public void removeAbility(Ability ability) {
		abilities.remove(ability);
	}

	public void removeAllAbilities() {
		abilities = new HashMap<Long, Ability>();

	}

	public Set<Ability> getAbilities() {
		Set<Ability> result = new HashSet<Ability>();
		result.addAll(abilities.values());
		return result;
	}

	public boolean hasTrigger(AbilityTrigger trigger) {
		Collection<Ability> abilities = getAbilities();
		for (Ability ability : abilities) {
			if (ability.getTrigger().equals(trigger)) {
				return true;
			}
		}
		return false;
	}

	public Set<Ability> getAbilities(AbilityTrigger trigger) {
		Set<Ability> result = new HashSet<Ability>();
		Collection<Ability> abilities = getAbilities();
		for (Ability ability : abilities) {
			if (ability.getTrigger().equals(trigger)) {
				result.add(ability);
			}
		}
		return result;
	}

	public String toString() {
		StringBuilder abilitySB = new StringBuilder();
		for (Ability ability : abilities.values()) {
			abilitySB.append(ability);
		}
		return abilitySB.toString();
	}

	public void registerAbilities() {
		for (Ability ability : abilities.values()) {
			// ability.setCard(playingCard);
			AbilityTrigger trigger = ability.getTrigger();
			trigger.register();
		}

	}

	public void unRegisterAbilities() {
		for (Ability ability : abilities.values()) {
			AbilityTrigger trigger = ability.getTrigger();
			trigger.unRegister();
		}

	}
	
	public int size(){
		return abilities.size();
	}

}
